package de.tud.binpacking.heuristic.construction;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import de.tud.binpacking.data.Batch;
import de.tud.binpacking.data.Order;
import de.tud.binpacking.instance.Instance;

public class NearestNeighborAisles extends AStartHeuristic {

	public NearestNeighborAisles(Instance instance) {
		super(instance);
	}

	@Override
	public String toString() {
		return "Nearest Neighbor - add the next best matching order, by aisles orderd by aisles";
	}

	@Override
	protected boolean findSolution() {
		List<Batch> batches = new ArrayList<Batch>();
		
		//Order by num of Aisles
		List<Order> orders = this.instance.getOrders();
		Collections.sort(orders, new OrderComparator());
		batches.add(new Batch(instance, orders.get(0)));
		orders.remove(0);
				
		for(final Order order : orders) {
			
			int smallestDistance = Integer.MAX_VALUE;
			Batch curBestBatch = null;
			for(final Batch batch : batches) {
				
				if(batch.getFreeCapacity() >= order.size()) {
					int distance = calcDistance(order, batch);
					if(distance < smallestDistance) {
						smallestDistance = distance;
						curBestBatch = batch;
					}
				} else continue;
			}
			if(curBestBatch == null) {
				batches.add(new Batch(instance, order));
			} else {
				curBestBatch.add(order);
			}
		}
		for(Batch batch : batches){
			solution.addBatch(batch);
		}
		return false;
	}
	
	private int calcDistance(Order order, Batch batch) {
		int distance = 0;
		
		for (int i : order.getAisles()) {
			if (!batch.getAisles().contains(i)) {
				distance++;
			}
		}
		
		return distance;
	}

	/**
	 * Order by Aisles > Size
	 * @author Michael
	 *
	 */
	private class OrderComparator implements Comparator<Order> {
		@Override
		public int compare(Order o1, Order o2) {
			int numOfAisleo1 = o1.getAisles().size();
			int numOfAisleo2 = o2.getAisles().size();
			if(numOfAisleo1 < numOfAisleo2) {
				return -1;
			} else if(numOfAisleo1 > numOfAisleo2) {
				return 1;
			} else {
				if(o1.size() < o2.size()) {
					return -1;
				} else if(o1.size() > o2.size()) {
					return 1;
				} else {
//					if(o1.getItems().get(o1.getItems().size()-1).getCell() < o2.getItems().get(o2.getItems().size()-1).getCell()) {
//						return -1;
//					}else if(o1.getItems().get(o1.getItems().size()-1).getCell() > o2.getItems().get(o2.getItems().size()-1).getCell()) {
//						return 1;
//					} else {
						return 0;
//					}
				}	
			}
		}
	}
		
	
}
